/*!  \file  TaskManager.h
 *	  \brief  
 * 
 *   \details   details
 *   \author    Yordan Madzhunkov German Research School for Simulation Sciences GmbH
 *   \version   1.0
 *   \date      07/14/2013 01:19:32 PM
 *   \copyright GNU Public License.
 */
#pragma once
class Lock;
class Task;
class GKManager;
struct Link;

class TaskManager {
public:
	TaskManager();
	virtual ~TaskManager();
	bool perform     (Task & t, const int nThreads_); 
	void addToReady  (const TaskID taskID);
	void reset();

	void * workerFunction(const int tID) ; // enterence point for all threads	
	Task & getTask( const int ID ) const { return taskStorage[ID]; };
	TaskID myID(const Task * p) { return p - taskStorage; };	
	int getNThreads() const { return nThreads; };
	bool allocateTaskID(TaskID & taskID, const int tID) {
		bool res = taskIDPool->allocate(taskID, tID);
		return res;
		
	}
	Lock & getLock(Task * t) { return getLockForTask(myID(t));};
	Lock & getLockForTask(TaskID taskID) {
		return locks[taskID % maxNLocks];
	}
	Lock & getLock(const int i) { return locks[i];};
	void finish() { notFinished = false; }
	void setN(const int n_); 
	int getN() const { return n; };

	GKManager * getGKManager() const { return gkManager; };
	int getReadyQueueSize() const { return ready->size(); };

private:
	DISALLOW_COPY_AND_ASSIGN(TaskManager);
	void delocate();
	void allocate();
	void process(TaskID taskID, const int tID);
	void informParent(const TaskID parentID, const TaskID childID, 
		const int tID);

	NoLimitQueue<int> * ready ;// taskIDs of all task ready to be executed
	Task       * taskStorage  ;// array of task objects
	MemoryPool * taskIDPool   ;// taskID allocator
	Lock       * locks        ;// some locks 
	GKManager  * gkManager    ;// mageger for assigning GK matrix for tasks

	int maxNTasks; 
	int maxNLinks; 
	int maxNTaskInQueue;
	int maxNLocks;
	int maxNNodes; 
	int maxNGK;
	int nThreads;
	int n;
	bool needAllocation;
	volatile bool notFinished;
};
